Skip to content

obj2yaml: Add "detailed" output in CovMap dump #129473

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 3 commits into
base: users/chapuni/yaml/covmap
Choose a base branch
from

Conversation

chapuni
Copy link
Contributor

@chapuni chapuni commented Mar 3, 2025

Depends on #127432

@llvmbot
Copy link
Member

llvmbot commented Mar 3, 2025

@llvm/pr-subscribers-objectyaml

Author: NAKAMURA Takumi (chapuni)

Changes

Depends on #127432


Patch is 23.21 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/129473.diff

5 Files Affected:

  • (modified) llvm/include/llvm/ObjectYAML/CovMap.h (+87-10)
  • (modified) llvm/lib/ObjectYAML/CovMap.cpp (+151-39)
  • (modified) llvm/test/tools/obj2yaml/ELF/covmap-be.yaml (+7)
  • (modified) llvm/test/tools/obj2yaml/ELF/covmap.yaml (+7)
  • (modified) llvm/tools/obj2yaml/elf2yaml.cpp (+17-8)
diff --git a/llvm/include/llvm/ObjectYAML/CovMap.h b/llvm/include/llvm/ObjectYAML/CovMap.h
index 406204ee024fb..b55d902f999e8 100644
--- a/llvm/include/llvm/ObjectYAML/CovMap.h
+++ b/llvm/include/llvm/ObjectYAML/CovMap.h
@@ -24,6 +24,7 @@
 #define LLVM_OBJECTYAML_COVMAP_H
 
 #include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/DenseMap.h"
 #include "llvm/ADT/StringRef.h"
 #include "llvm/ObjectYAML/ELFYAML.h"
 #include "llvm/Support/Endian.h"
@@ -34,14 +35,67 @@
 #include <memory>
 #include <optional>
 #include <string>
+#include <variant>
 #include <vector>
 
 namespace llvm {
+class InstrProfSymtab;
 class raw_ostream;
 } // namespace llvm
 
 namespace llvm::coverage::yaml {
 
+/// This works like vector container but can be replaced with
+/// MutableArrayRef. See also SequenceTraits<VectorOrRef>.
+template <typename T, typename Vec = std::vector<T>> class VectorOrRef {
+  using Ref = MutableArrayRef<T>;
+
+  /// Holds vector type initially.
+  std::variant<Vec, Ref> Array;
+
+public:
+  // FIXME: Iterator impl is minimal easy.
+  using iterator = T *;
+
+  iterator begin() {
+    if (auto *V = std::get_if<Vec>(&Array))
+      return &V->front();
+    return &std::get<Ref>(Array).front();
+  }
+
+  iterator end() {
+    if (auto *V = std::get_if<Vec>(&Array))
+      return &V->back() + 1;
+    return &std::get<Ref>(Array).back() + 1;
+  }
+
+  size_t size() const {
+    if (const auto *V = std::get_if<Vec>(&Array))
+      return V->size();
+    return std::get<Ref>(Array).size();
+  }
+
+  T &operator[](int Idx) {
+    if (auto *V = std::get_if<Vec>(&Array))
+      return (*V)[Idx];
+    return std::get<Ref>(Array)[Idx];
+  }
+
+  void resize(size_t Size) { std::get<Vec>(Array).resize(Size); }
+
+  VectorOrRef() = default;
+
+  /// Initialize with MutableArrayRef.
+  VectorOrRef(Ref &&Tmp) : Array(std::move(Tmp)) {}
+};
+
+/// Options for Decoder.
+struct DecoderParam {
+  bool Detailed; ///< Generate and show processed records.
+  bool Raw;      ///< Show raw data oriented records.
+  bool dLoc;     ///< Show raw dLoc (differential Loc).
+};
+
 struct DecoderContext;
 
 /// Base Counter, corresponding to coverage::Counter.
@@ -143,6 +197,9 @@ struct FileRecsTy {
   void mapping(llvm::yaml::IO &IO);
 };
 
+/// Key is FilenamesRef.
+using CovMapByRefTy = llvm::DenseMap<uint64_t, struct CovMapTy *>;
+
 /// An element of CovFun array.
 struct CovFunTy {
   std::optional<llvm::yaml::Hex64> NameRef;     ///< Hash value of the symbol.
@@ -157,7 +214,8 @@ struct CovFunTy {
 
   /// Depends on CovMap and SymTab(IPSK_names)
   Expected<uint64_t> decode(const ArrayRef<uint8_t> Content, uint64_t Offset,
-                            endianness Endianness);
+                            endianness Endianness, CovMapByRefTy &CovMapByRef,
+                            InstrProfSymtab *SymTab, const DecoderParam &Param);
 
   void encode(raw_ostream &OS, endianness Endianness) const;
 };
@@ -180,7 +238,7 @@ struct CovMapTy {
   /// This may be ArrayRef in Decoder since Filenames has been
   /// filled. On the other hand in Encoder, this should be a vector
   /// since YAML parser doesn't endorse references.
-  std::optional<std::vector<std::string>> Files;
+  std::optional<VectorOrRef<std::string>> Files;
 
   void mapping(llvm::yaml::IO &IO);
 
@@ -188,7 +246,7 @@ struct CovMapTy {
   StringRef getWD() const { return (WD ? *WD : StringRef()); }
 
   Expected<uint64_t> decode(const ArrayRef<uint8_t> Content, uint64_t Offset,
-                            endianness Endianness);
+                            endianness Endianness, const DecoderParam &Param);
 
   /// Generate Accumulated list with WD.
   /// Returns a single element {WD} if AccFiles is not given.
@@ -210,6 +268,21 @@ struct CovMapTy {
 
 } // namespace llvm::coverage::yaml
 
+namespace llvm::yaml {
+template <typename T>
+struct SequenceTraits<llvm::coverage::yaml::VectorOrRef<T>> {
+  static size_t size(IO &io, llvm::coverage::yaml::VectorOrRef<T> &seq) {
+    return seq.size();
+  }
+  static T &element(IO &, llvm::coverage::yaml::VectorOrRef<T> &seq,
+                    size_t index) {
+    if (index >= seq.size())
+      seq.resize(index + 1);
+    return seq[index];
+  }
+};
+} // namespace llvm::yaml
+
 LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::coverage::yaml::CovMapTy)
 LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::coverage::yaml::CovFunTy)
 LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::coverage::yaml::ExpressionTy)
@@ -265,17 +338,21 @@ class Decoder {
   virtual ~Decoder() {}
 
   /// Returns DecoderImpl.
-  static std::unique_ptr<Decoder> get(endianness Endianness,
-                                      bool CovMapEnabled);
+  static std::unique_ptr<Decoder>
+  get(endianness Endianness, const coverage::yaml::DecoderParam &Param);
 
   /// Called from the Sections loop in advance of the final dump.
-  /// Decoder predecodes CovMap for Version info.
-  virtual Error acquire(unsigned AddressAlign, StringRef Name,
+  /// Decoder predecodes Names and CovMap, and captures Contents of
+  /// CovFuns.
+  virtual Error acquire(uint64_t Offset, unsigned AddressAlign, StringRef Name,
                         ArrayRef<uint8_t> Content) = 0;
 
-  /// Make contents on ELFYAML object. CovMap is predecoded.
-  virtual Error make(ELFYAML::CovMapSectionBase *Base,
-                     ArrayRef<uint8_t> Content) = 0;
+  /// Called before the final dump after `acquire`.
+  /// Decode contents partially and resolve names.
+  virtual Error fixup() = 0;
+
+  /// Make contents on ELFYAML object with predecoded contents.
+  virtual Error make(ELFYAML::CovMapSectionBase *Base, uint64_t Offset) = 0;
 
   /// Suppress emission of CovMap unless enabled.
   static bool enabled;
diff --git a/llvm/lib/ObjectYAML/CovMap.cpp b/llvm/lib/ObjectYAML/CovMap.cpp
index dcf90f7b109cb..94970cd41d5a7 100644
--- a/llvm/lib/ObjectYAML/CovMap.cpp
+++ b/llvm/lib/ObjectYAML/CovMap.cpp
@@ -13,8 +13,10 @@
 #include "llvm/ObjectYAML/CovMap.h"
 #include "llvm/ADT/ArrayRef.h"
 #include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/MapVector.h"
 #include "llvm/ADT/SmallVector.h"
 #include "llvm/ObjectYAML/ELFYAML.h"
+#include "llvm/ProfileData/Coverage/CoverageMapping.h"
 #include "llvm/ProfileData/Coverage/CoverageMappingReader.h"
 #include "llvm/ProfileData/Coverage/CoverageMappingWriter.h"
 #include "llvm/ProfileData/InstrProf.h"
@@ -42,12 +44,15 @@ using namespace llvm::covmap;
 bool Decoder::enabled;
 
 // DataExtractor w/ single Cursor
-struct coverage::yaml::DecoderContext : DataExtractor, DataExtractor::Cursor {
+struct coverage::yaml::DecoderContext : DataExtractor,
+                                        DataExtractor::Cursor,
+                                        DecoderParam {
   uint64_t LineStart = 0;
 
-  DecoderContext(const ArrayRef<uint8_t> Content, bool IsLE)
+  DecoderContext(const ArrayRef<uint8_t> Content, bool IsLE,
+                 const DecoderParam &Param)
       : DataExtractor(Content, IsLE, /*AddressSize=*/0),
-        DataExtractor::Cursor(0) {}
+        DataExtractor::Cursor(0), DecoderParam(Param) {}
 
   bool eof() { return DataExtractor::eof(*this); }
   uint32_t getU32() { return DataExtractor::getU32(*this); }
@@ -91,8 +96,24 @@ Error CounterTy::decodeOrTag(DecoderContext &Data) {
     else
       Val = V; // w/o Tag
   } else {
-    Tag = T;
-    Val = V;
+    if (Data.Raw) {
+      Tag = T;
+      Val = V;
+    } else {
+      switch (T) {
+      case Zero:
+        llvm_unreachable("Zero should be handled in advance");
+      case Ref:
+        RefOpt = V;
+        break;
+      case Sub:
+        SubOpt = V;
+        break;
+      case Add:
+        AddOpt = V;
+        break;
+      }
+    }
   }
 
   return Error::success();
@@ -211,12 +232,14 @@ Error RecTy::decode(DecoderContext &Data) {
     case Decision:
       if (auto E = DecisionOpt.emplace().decode(Data))
         return E;
-      ExtTag = Decision;
+      if (Data.Raw)
+        ExtTag = Decision;
       break;
     case Branch:
       if (auto E = decodeBranch())
         return E;
-      ExtTag = Branch;
+      if (Data.Raw)
+        ExtTag = Branch;
       break;
     case MCDCBranch: {
       if (auto E = decodeBranch())
@@ -231,7 +254,8 @@ Error RecTy::decode(DecoderContext &Data) {
       if (!I2OrErr)
         return I2OrErr.takeError();
       MCDC = {*I0OrErr, *I1OrErr, *I2OrErr};
-      ExtTag = MCDCBranch;
+      if (Data.Raw)
+        ExtTag = MCDCBranch;
       break;
     }
     default:
@@ -363,8 +387,11 @@ CovMapTy::encodeFilenames(const std::optional<ArrayRef<StringRef>> &AccFilesOpt,
 }
 
 Expected<uint64_t> CovFunTy::decode(const ArrayRef<uint8_t> Content,
-                                    uint64_t Offset, endianness Endianness) {
-  DecoderContext Data(Content, (Endianness == endianness::little));
+                                    uint64_t Offset, endianness Endianness,
+                                    CovMapByRefTy &CovMapByRef,
+                                    InstrProfSymtab *Symtab,
+                                    const DecoderParam &Param) {
+  DecoderContext Data(Content, (Endianness == endianness::little), Param);
   Data.seek(Offset);
 
   uint32_t DataSize;
@@ -383,9 +410,17 @@ Expected<uint64_t> CovFunTy::decode(const ArrayRef<uint8_t> Content,
   if (!Data)
     return Data.takeError();
 
+  if (Data.Detailed)
+    FuncName = Symtab->getFuncOrVarNameIfDefined(*NameRef);
+
+  if (!Data.Raw)
+    NameRef.reset();
+
   [[maybe_unused]] auto ExpectedEndOffset = Data.tell() + DataSize;
 
   // Decode body.
+  assert(CovMapByRef.contains(this->FilenamesRef));
+  auto &CovMap = *CovMapByRef[this->FilenamesRef];
   FileIDs.emplace();
 
   auto NumFilesOrErr = Data.getULEB128();
@@ -414,6 +449,10 @@ Expected<uint64_t> CovFunTy::decode(const ArrayRef<uint8_t> Content,
     if (!NumRegionsOrErr)
       return NumRegionsOrErr.takeError();
     auto &File = Files.emplace_back();
+    if (Data.Detailed) {
+      File.Index = FileIdx; // Sequential number.
+      File.Filename = (*CovMap.Filenames)[(*FileIDs)[FileIdx]];
+    }
 
     // Decode subarray.
     Data.LineStart = 0;
@@ -421,9 +460,19 @@ Expected<uint64_t> CovFunTy::decode(const ArrayRef<uint8_t> Content,
       auto &Rec = File.Recs.emplace_back();
       if (auto E = Rec.decode(Data))
         return std::move(E);
+
+      // Hide either Loc or dLoc.
+      if (!Data.Detailed || Data.dLoc)
+        Rec.Loc.reset();
+      else if (!Data.Raw)
+        Rec.dLoc.reset();
     }
   }
 
+  // Hide FileIDs.
+  if (!Data.Raw)
+    FileIDs.reset();
+
   assert(Data.tell() == ExpectedEndOffset);
   return Data.tell();
 }
@@ -454,8 +503,9 @@ void CovMapTy::encode(raw_ostream &OS, endianness Endianness) const {
 }
 
 Expected<uint64_t> CovMapTy::decode(const ArrayRef<uint8_t> Content,
-                                    uint64_t Offset, endianness Endianness) {
-  DecoderContext Data(Content, (Endianness == endianness::little));
+                                    uint64_t Offset, endianness Endianness,
+                                    const DecoderParam &Param) {
+  DecoderContext Data(Content, (Endianness == endianness::little), Param);
   Data.seek(Offset);
 
 #define COVMAP_HEADER(Type, LLVMType, Name, Initializer)                       \
@@ -479,6 +529,17 @@ Expected<uint64_t> CovMapTy::decode(const ArrayRef<uint8_t> Content,
                    .read(static_cast<CovMapVersion>(Version)))
     return E;
 
+  if (Param.Detailed && useWD()) {
+    assert(this->Filenames->size() >= 1);
+    auto FilenamesI = this->Filenames->begin();
+    StringRef WD = *FilenamesI++;
+    if (!WD.empty())
+      this->WD = WD;
+    // Use Filenames as a storage.
+    this->Files.emplace(
+        MutableArrayRef(&*FilenamesI, &*this->Filenames->end()));
+  }
+
   Offset = Data.tell();
   return Offset;
 }
@@ -527,7 +588,12 @@ void CovFunTy::mapping(llvm::yaml::IO &IO) {
 void CovMapTy::mapping(llvm::yaml::IO &IO) {
   IO.mapRequired("FilenamesRef", FilenamesRef);
   IO.mapOptional("Version", Version);
-  IO.mapOptional("Filenames", Filenames);
+
+  if (!WD && !Files)
+    // Suppress this regardless of (Detailed && Raw).
+    // Since it is obviously redundant.
+    IO.mapOptional("Filenames", Filenames);
+
   IO.mapOptional("WD", WD);
   IO.mapOptional("Files", Files);
 }
@@ -592,7 +658,7 @@ struct CovMapSection : ELFYAML::CovMapSectionBase {
   }
 
   Error decode(ArrayRef<uint8_t> Blob, unsigned AddressAlign,
-               endianness Endianness) {
+               endianness Endianness, const DecoderParam &Param) {
     uint64_t Offset = 0;
 
     while (true) {
@@ -601,7 +667,7 @@ struct CovMapSection : ELFYAML::CovMapSectionBase {
         break;
       }
       auto &CovMap = CovMaps.emplace_back();
-      auto Result = CovMap.decode(Blob, Offset, Endianness);
+      auto Result = CovMap.decode(Blob, Offset, Endianness, Param);
       if (!Result) {
         return Result.takeError();
       }
@@ -637,9 +703,10 @@ struct CovFunSection : ELFYAML::CovMapSectionBase {
     IO.mapOptional("CovFun", CovFuns);
   }
 
-  static Expected<std::vector<CovFunTy>> decode(ArrayRef<uint8_t> CovFunA,
-                                                unsigned AddressAlign,
-                                                endianness Endianness) {
+  static Expected<std::vector<CovFunTy>>
+  decode(ArrayRef<uint8_t> CovFunA, unsigned AddressAlign,
+         endianness Endianness, CovMapByRefTy &CovMapByRef,
+         InstrProfSymtab *Symtab, const DecoderParam &Param) {
     std::vector<CovFunTy> CovFuns;
     uint64_t Offset = 0;
 
@@ -649,7 +716,8 @@ struct CovFunSection : ELFYAML::CovMapSectionBase {
         break;
 
       auto &CovFun = CovFuns.emplace_back();
-      auto Result = CovFun.decode(CovFunA, Offset, Endianness);
+      auto Result = CovFun.decode(CovFunA, Offset, Endianness, CovMapByRef,
+                                  Symtab, Param);
       if (!Result)
         return Result.takeError();
 
@@ -675,7 +743,7 @@ class CovMapFilenamesResolver {
   std::vector<CovFunTy *> UnresolvedCovFuns;
 
 protected:
-  DenseMap<uint64_t, struct CovMapTy *> CovMapByRef;
+  CovMapByRefTy CovMapByRef;
   std::vector<CovMapTy> TempCovMaps; // For Decoder
 
 public:
@@ -702,6 +770,23 @@ class CovMapFilenamesResolver {
     }
   }
 
+  void decMaybeResetFilenames(std::vector<CovMapTy> &CovMaps) {
+    for (auto &CovMap : CovMaps) {
+      auto FilenamesI = FilenamesByCovMap.find(CovMap.FilenamesRef);
+      if (FilenamesI == FilenamesByCovMap.end())
+        continue;
+
+      // Calculate FilenamesRef with Filenames from CovFuns.
+      // If matches, hide Filenames from CovMap.
+      auto [AccFilenamesRef, _] =
+          CovMap.encodeFilenames(FilenamesI->second.getArrayRef());
+      if (CovMap.FilenamesRef == AccFilenamesRef) {
+        CovMap.Files.reset();
+        CovMap.Filenames.reset(); // FilenamesI has been invalidated.
+      }
+    }
+  }
+
   void encFixup() {
     for (auto &[_, CovMap] : CovMapByRef) {
       auto FilenamesI = FilenamesByCovMap.find(CovMap->FilenamesRef);
@@ -757,15 +842,23 @@ class CovMapFilenamesResolver {
 };
 
 class DecoderImpl : public Decoder, CovMapFilenamesResolver {
+  DecoderParam Param;
+
   std::unique_ptr<InstrProfSymtab> ProfileNames;
 
+  InstrProfSymtab::PrfNamesChunksTy PrfNames;
+
+  MapVector<uint64_t, std::pair<ArrayRef<uint8_t>, unsigned>> CovFunBlobs;
+  DenseMap<uint64_t, std::vector<CovFunTy>> TempCovFuns;
+
 public:
-  DecoderImpl(endianness Endianness, bool CovMapEnabled)
-      : Decoder(Endianness), ProfileNames(std::make_unique<InstrProfSymtab>()) {
-    enabled = CovMapEnabled;
+  DecoderImpl(endianness Endianness, const DecoderParam &Param)
+      : Decoder(Endianness), Param(Param),
+        ProfileNames(std::make_unique<InstrProfSymtab>()) {
+    enabled = (Param.Detailed || Param.Raw);
   }
 
-  Error acquire(unsigned AddressAlign, StringRef Name,
+  Error acquire(uint64_t Offset, unsigned AddressAlign, StringRef Name,
                 ArrayRef<uint8_t> Content) override {
     // Don't register anything.
     if (!enabled)
@@ -775,33 +868,52 @@ class DecoderImpl : public Decoder, CovMapFilenamesResolver {
       // Decode CovMaps in advance, since only CovMap knows its Version.
       // CovMaps is restored (into CovMapSection) later.
       auto TempCovMap = std::make_unique<CovMapSection>();
-      if (auto E = TempCovMap->decode(Content, AddressAlign, Endianness))
+      if (auto E = TempCovMap->decode(Content, AddressAlign, Endianness, Param))
         return E;
       moveAndCollectCovMap(std::move(TempCovMap->CovMaps));
+    } else if (PrfNamesSection::nameMatches(Name)) {
+      // Decode PrfNames in advance since CovFun depends on it.
+      auto PrfNamesOrErr = ProfileNames->createAndGetList(Content);
+      if (!PrfNamesOrErr)
+        return PrfNamesOrErr.takeError();
+      PrfNames = std::move(*PrfNamesOrErr);
+    } else if (CovFunSection::nameMatches(Name)) {
+      // Will be decoded after CovMap is met.
+      CovFunBlobs[Offset] = {Content, AddressAlign};
     }
 
     return Error::success();
   }
 
-  Error make(ELFYAML::CovMapSectionBase *Base,
-             ArrayRef<uint8_t> Content) override {
+  Error fixup() override {
+    // Decode CovFun(s) with predecoded PrfNames and CovMap.
+    for (const auto &[Offset, CovFunBlob] : CovFunBlobs) {
+      auto CovFunsOrErr =
+          CovFunSection::decode(CovFunBlob.first, CovFunBlob.second, Endianness,
+                                CovMapByRef, ProfileNames.get(), Param);
+      if (!CovFunsOrErr)
+        return CovFunsOrErr.takeError();
+      TempCovFuns[Offset] = std::move(*CovFunsOrErr);
+      collectCovFunFilenames(TempCovFuns[Offset]);
+    }
+    // Hide Filenames if it is reproducible from CovFuns.
+    if (Param.Detailed)
+      decMaybeResetFilenames(TempCovMaps);
+    return Error::success();
+  }
+
+  Error make(ELFYAML::CovMapSectionBase *Base, uint64_t Offset) override {
     if (auto *S = dyn_cast<CovMapSection>(Base)) {
       // Store predecoded CovMaps.
       S->CovMaps = std::move(TempCovMaps);
       return Error::success();
     } else if (auto *S = dyn_cast<PrfNamesSection>(Base)) {
-      // Decode PrfNames in advance since CovFun depends on it.
-      auto PrfNamesOrErr = ProfileNames->createAndGetList(Content);
-      if (!PrfNamesOrErr)
-        return PrfNamesOrErr.takeError();
-      S->PrfNames = std::move(*PrfNamesOrErr);
+      S->PrfNames = std::move(PrfNames);
       return Error::success();
     } else if (auto *S = dyn_cast<CovFunSection>(Base)) {
-      auto CovFunsOrErr =
-          CovFunSection::decode(Content, S->AddressAlign, Endianness);
-      if (!CovFunsOrErr)
-        return CovFunsOrErr.takeError();
-      S->CovFuns = std::move(*CovFunsOrErr);
+      assert(S->CovFuns.empty());
+      assert(TempCovFuns.contains(Offset));
+      S->CovFuns = std::move(TempCovFuns[Offset]);
       return Error::success();
     }
 
@@ -826,8 +938,8 @@ class EncoderImpl : public Encoder, CovMapFilenamesResolver {
 } // namespace
 
 std::unique_ptr<Decoder> Decoder::get(endianness Endianness,
-                                      bool CovMapEnabled) {
-  return std::make_unique<DecoderImpl>(Endianness, CovMapEnabled);
+                                      const DecoderParam &Param) {
+  return std::make_unique<DecoderImpl>(Endianness, Param);
 }
 
 std::unique_ptr<Encoder> Encoder::get(endianness Endianness) {
diff --git a/llvm/test/tools/obj2yaml/ELF/covmap-be.yaml b/llvm/test/tools/obj2yaml/ELF/covmap-be.yaml
index 8423f1ad5f765..ec1352b40a9cc 100644
--- a/llvm/test/tools/obj2yaml/ELF/covmap-be.yaml
+++ b/llvm/test/tools/obj2yaml/ELF/covmap-be.yaml
@@ -1,8 +1,15 @@
 # RUN: yaml2obj %s -o %t.o
 # RUN: obj2yaml %t.o > %t.plain.yaml
 # RUN: obj2yaml --covmap-raw %t.o > %t.raw.yaml
+# RUN: obj2yaml --covmap --covmap-raw %t.o > %t.mixed.yaml
+# RUN: obj2yaml --covmap --covmap-dloc %t.o > %t.dloc.yaml
+# RUN: obj2yaml --covmap %t.o > %t.covmap.yaml
+# RUN: sed -E '/^(#.*)?$/d' %s | diff %t.covmap.yaml -
 # RUN: yaml2obj %t.plain.yaml -o - | cmp %t.o -
 # RUN: yaml2obj %t.raw.yaml -o - | cmp %t.o -
+# RUN: yaml2obj %t.mixed.yaml -o - | cmp %t.o -
+# RUN: yaml2obj %t.dloc.yaml -o - | cmp %t.o -
+# RUN: yaml2obj %t.covmap.yaml -o - | cmp %t.o -
 
 # FIXME: This is synthetically created. s/ELFDATA2LSB/ELF2DATAMSB/ s/EM_X86_64/EM_PPC64/
 --- !ELF
diff --git a/llvm/test/tools/obj2yaml/ELF/covmap.yaml b/llvm/test/tools/obj2yaml/ELF/covmap.yaml
index db30d373d5be1..fc77a3d02f909...
[truncated]

@chapuni chapuni requested a review from jh7370 March 3, 2025 04:29
chapuni added 2 commits March 7, 2025 12:43
…iled

Conflicts:
	llvm/include/llvm/ObjectYAML/CovMap.h
	llvm/lib/ObjectYAML/CovMap.cpp
	llvm/test/tools/obj2yaml/ELF/covmap.yaml
…iled

Conflicts:
	llvm/test/tools/obj2yaml/ELF/covmap.yaml
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants